package com.xiaoyu.lanling.feature.profile.activity

import `in`.srain.cube.util.TimeUtils
import `in`.srain.cube.util.internal.AppCallback
import android.app.ProgressDialog
import android.media.MediaPlayer
import android.os.Bundle
import android.view.View
import androidx.annotation.Keep
import androidx.recyclerview.widget.ItemTouchHelper
import com.xiaoyu.base.app.AppContext
import com.xiaoyu.base.data.UserData
import com.xiaoyu.base.event.AppEventBus
import com.xiaoyu.base.event.SimpleEventHandler
import com.xiaoyu.base.model.User
import com.xiaoyu.base.utils.ListUtil
import com.xiaoyu.base.utils.RxUtils
import com.xiaoyu.base.utils.extensions.getViewTag
import com.xiaoyu.base.utils.extensions.setOnClickDebounceListener
import com.xiaoyu.base.utils.extensions.setViewTag
import com.xiaoyu.base.utils.upload.UploadImageOriginalType
import com.xiaoyu.base.utils.upload.UploadMediaType
import com.xiaoyu.base.utils.upload.UploadParam
import com.xiaoyu.lanling.R
import com.xiaoyu.lanling.activity.base.AppCompatToolbarActivity
import com.xiaoyu.lanling.common.Constant
import com.xiaoyu.lanling.event.media.mediaselector.MediaSelectorResultEvent
import com.xiaoyu.lanling.event.user.*
import com.xiaoyu.lanling.feature.profile.data.UserInfoEditProvider
import com.xiaoyu.lanling.feature.profile.data.UserInfoEditProvider.Companion.HEIGHT_DEFAULT
import com.xiaoyu.lanling.feature.profile.fragment.AvatarDemoBottomSheetDialog
import com.xiaoyu.lanling.feature.profile.model.UserProfile
import com.xiaoyu.lanling.feature.profile.model.UserProfile.Companion.MAX_ALBUM_COUNT
import com.xiaoyu.lanling.feature.profile.model.UserVoiceModel
import com.xiaoyu.lanling.feature.user.data.UserInfoData
import com.xiaoyu.lanling.feature.user.model.UserAlbumItem
import com.xiaoyu.lanling.feature.user.viewholder.UserAlbumViewHolder
import com.xiaoyu.lanling.feature.view.weight.picker.single.PickerSingleBottomSheetDialog
import com.xiaoyu.lanling.media.image.ImageViewUtil
import com.xiaoyu.lanling.media.selector.MediaSelector
import com.xiaoyu.lanling.media.selector.MediaSelectorFromType.USER_ALBUM
import com.xiaoyu.lanling.media.selector.MediaSelectorFromType.USER_INFO_EDIT
import com.xiaoyu.lanling.media.selector.MediaSelectorType.IMAGE
import com.xiaoyu.lanling.router.Router
import com.xiaoyu.lanling.util.ImageFileCompressUtils
import com.xiaoyu.lanling.util.MP3PlayerUtils
import com.xiaoyu.lanling.util.upload.UploadCategory
import com.xiaoyu.lanling.view.AlertHoloDateDialog
import com.xiaoyu.lanling.view.ItemLeftAndRightTouchHelperCallback
import com.xiaoyu.lanling.view.adapter.ItemMovedListener
import com.xiaoyu.lanling.view.adapter.RecyclerViewDragAdapter
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_user_profile.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.*
import java.util.concurrent.TimeUnit

@Keep
class UserProfileActivity : AppCompatToolbarActivity(), ItemMovedListener {

    private val onStatusListener = object : MP3PlayerUtils.OnStatusListener {
        override fun OnPlaying(mp: MediaPlayer?) {
        }

        override fun OnError(what: String?, extra: String?) {
            voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_success, 0, 0, 0)
            mVoicePlayerDisposable?.dispose()
        }

        override fun onCompletion(mp: MediaPlayer?) {
            mp?.let {
                voice.text = getString(R.string.user_profile_voice_success, (it.duration / 1000).toString())
            }
            voice.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_success, 0, 0, 0)
            mVoicePlayerDisposable?.dispose()
        }

        override fun OnPrepared(mp: MediaPlayer?) {
            updatePlayLayout()
        }
    }

    private lateinit var heightPicker: PickerSingleBottomSheetDialog
    private lateinit var weightPicker: PickerSingleBottomSheetDialog
    private lateinit var sizePicker: PickerSingleBottomSheetDialog
    private lateinit var glamorPlacePicker: PickerSingleBottomSheetDialog
    private lateinit var annualIncomePicker: PickerSingleBottomSheetDialog
    private lateinit var educationDegreePicker: PickerSingleBottomSheetDialog
    private lateinit var emotionStatusPicker: PickerSingleBottomSheetDialog
    private lateinit var inhabitStatusPicker: PickerSingleBottomSheetDialog
    private lateinit var premaritalLivingPicker: PickerSingleBottomSheetDialog
    private lateinit var acceptDatesPicker: PickerSingleBottomSheetDialog
    private lateinit var houseDatesPicker: PickerSingleBottomSheetDialog
    private lateinit var carPicker: PickerSingleBottomSheetDialog
    private lateinit var drinkPicker: PickerSingleBottomSheetDialog
    private lateinit var cookLevelPicker: PickerSingleBottomSheetDialog

    private val progressDialog by lazy { ProgressDialog(this@UserProfileActivity) }
    private val adapter = RecyclerViewDragAdapter<UserAlbumItem>(this)

    private var mVoicePlayerDisposable: Disposable? = null

    private val itemDragCallback = ItemLeftAndRightTouchHelperCallback(adapter).apply {
        isLongPressDragEnabled = true
    }

    private val requestTag: Any = Any()

    private var mProfile: UserProfile? = null
    private var mAvatarDisposable: Disposable? = null
    private var mPhotoDisposable: Disposable? = null

    override fun onCreateSafelyAfterAppFinishInit(savedInstanceState: Bundle?) {
        super.onCreateSafelyAfterAppFinishInit(savedInstanceState)
        setLightStatusBar()
        setContentView(R.layout.activity_user_profile)
        initToolbar()

        initView()
        initAdapter()
        initBind()
        initEvent()
        initData()
    }

    private fun initAdapter() {
        adapter.setViewHolderClass(0, null, UserAlbumViewHolder::class.java, 10)
        album_recyclerview.adapter = adapter
    }

    override fun onStartSafelyAfterAppFinishInit(isFirstTimeStart: Boolean) {
        super.onStartSafelyAfterAppFinishInit(isFirstTimeStart)

        resumeVoice()
    }

    override fun onStop() {
        super.onStop()
        pauseVoice()
    }

    override fun onDestroy() {
        super.onDestroy()
        destroyVoice()
        mAvatarDisposable?.dispose()
        mPhotoDisposable?.dispose()
    }

    private fun initView() {
        heightPicker = PickerSingleBottomSheetDialog.create(this)
        heightPicker.initData(UserInfoEditProvider.heightList)
        weightPicker = PickerSingleBottomSheetDialog.create(this)
        weightPicker.initData(UserInfoEditProvider.weightList)
        sizePicker = PickerSingleBottomSheetDialog.create(this)
        sizePicker.initData(UserInfoEditProvider.sizeList)
        glamorPlacePicker = PickerSingleBottomSheetDialog.create(this)
        glamorPlacePicker.initData(UserInfoEditProvider.glamorPlaceList)
        annualIncomePicker = PickerSingleBottomSheetDialog.create(this)
        annualIncomePicker.initData(UserInfoEditProvider.annualIncomeList)
        educationDegreePicker = PickerSingleBottomSheetDialog.create(this)
        educationDegreePicker.initData(UserInfoEditProvider.educationDegreeList)
        emotionStatusPicker = PickerSingleBottomSheetDialog.create(this)
        emotionStatusPicker.initData(UserInfoEditProvider.emotionStatusList)
        inhabitStatusPicker = PickerSingleBottomSheetDialog.create(this)
        inhabitStatusPicker.initData(UserInfoEditProvider.inhabitStatusList)
        premaritalLivingPicker = PickerSingleBottomSheetDialog.create(this)
        premaritalLivingPicker.initData(UserInfoEditProvider.premaritalLivingList)
        acceptDatesPicker = PickerSingleBottomSheetDialog.create(this)
        acceptDatesPicker.initData(UserInfoEditProvider.acceptDatesList)
        houseDatesPicker = PickerSingleBottomSheetDialog.create(this)
        houseDatesPicker.initData(UserInfoEditProvider.houseStatusList)
        carPicker = PickerSingleBottomSheetDialog.create(this)
        carPicker.initData(UserInfoEditProvider.carStatusList)
        drinkPicker = PickerSingleBottomSheetDialog.create(this)
        drinkPicker.initData(UserInfoEditProvider.drinkStatusList)
        cookLevelPicker = PickerSingleBottomSheetDialog.create(this)
        cookLevelPicker.initData(UserInfoEditProvider.cookLevelList)
    }

    private fun initBind() {
        album_add.setOnClickDebounceListener {
            val photos = it.getViewTag<List<UserAlbumItem>>() ?: return@setOnClickDebounceListener
            MediaSelector.instance.selectorForImage(MAX_ALBUM_COUNT - photos.size, false, USER_ALBUM, false)
        }
        voice_retry_record.setOnClickDebounceListener {
            Router.instance.gotoUserVoiceRecordActivity(this)
        }
        voice.setOnClickDebounceListener {
            val model = it.getViewTag<UserVoiceModel>() ?: return@setOnClickDebounceListener
            when (model.verifyStatus) {
                UserVoiceModel.VERIFYING -> {
                    return@setOnClickDebounceListener
                }
                else -> {
                    if (model.voiceUrl.isNotEmpty()) {
                        playVoice(model.voiceUrl)
                    } else {
                        Router.instance.gotoUserVoiceRecordActivity(this)
                    }
                }
            }
        }
        avatar_layout.setOnClickDebounceListener {
            AvatarDemoBottomSheetDialog.show(this.supportFragmentManager)
        }
        name_layout.setOnClickDebounceListener {
            Router.instance.gotoUserNameEditActivity(this)
        }
        birthday_layout.setOnClickDebounceListener {
            showTimePicker()
        }
        height_layout.setOnClickDebounceListener { heightPicker.scrollToPositionByValue(HEIGHT_DEFAULT).show() }
        weight_layout.setOnClickDebounceListener { weightPicker.scrollToPositionByValue(mProfile?.weight).show() }
        size_layout.setOnClickDebounceListener { sizePicker.scrollToPositionByValue(mProfile?.size).show() }
        glamor_place_layout.setOnClickDebounceListener { glamorPlacePicker.scrollToPositionByValue(mProfile?.glamorPlace).show() }
        annual_income_layout.setOnClickDebounceListener { annualIncomePicker.scrollToPositionByValue(mProfile?.annualIncome).show() }
        education_degree_layout.setOnClickDebounceListener { educationDegreePicker.scrollToPositionByValue(mProfile?.educationDegree).show() }
        emotion_status_layout.setOnClickDebounceListener { emotionStatusPicker.scrollToPositionByValue(mProfile?.emotionStatus).show() }
        inhabit_status_layout.setOnClickDebounceListener { inhabitStatusPicker.scrollToPositionByValue(mProfile?.inhabitStatus).show() }
        premarital_living_layout.setOnClickDebounceListener { premaritalLivingPicker.scrollToPositionByValue(mProfile?.premaritalLiving).show() }
        accept_dates_layout.setOnClickDebounceListener { acceptDatesPicker.scrollToPositionByValue(mProfile?.acceptDates).show() }
        house_layout.setOnClickDebounceListener { houseDatesPicker.scrollToPositionByValue(mProfile?.house).show() }
        car_layout.setOnClickDebounceListener { carPicker.scrollToPositionByValue(mProfile?.car).show() }
        drink_layout.setOnClickDebounceListener { drinkPicker.scrollToPositionByValue(mProfile?.drink).show() }
        cook_level_layout.setOnClickDebounceListener { cookLevelPicker.scrollToPositionByValue(mProfile?.cookLevel).show() }
        soliloquy_layout?.setOnClickDebounceListener {
            Router.instance.gotoUserSoliloquyEditActivity(this, mProfile?.soliloquy)
        }

        heightPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "height", model.key) }
        weightPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "weight", model.key) }
        sizePicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "size", model.key) }
        glamorPlacePicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "glamorPlace", model.key) }
        annualIncomePicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "annualIncome", model.key) }
        educationDegreePicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "educationDegree", model.key) }
        emotionStatusPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "emotionStatus", model.key) }
        inhabitStatusPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "inhabitStatus", model.key) }
        premaritalLivingPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "premaritalLiving", model.key) }
        acceptDatesPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "acceptDates", model.key) }
        houseDatesPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "house", model.key) }
        carPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "car", model.key) }
        drinkPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "drink", model.key) }
        cookLevelPicker.setOnPickResultListener { model -> UserInfoData.setProfile(requestTag, "cookLevel", model.key) }

        val itemTouchHelper = ItemTouchHelper(itemDragCallback)
        itemTouchHelper.attachToRecyclerView(album_recyclerview)
    }

    private fun playVoice(voiceUrl: String) {
        if (MP3PlayerUtils.getInstance().isPlaying) {
            pauseVoice()
        } else if (!MP3PlayerUtils.getInstance().isPlaying && MP3PlayerUtils.getInstance().isSamePath(voiceUrl)) {
            resumeVoice()
        } else {
            MP3PlayerUtils.getInstance().start(voiceUrl, onStatusListener)
        }
    }

    private fun initEvent() {
        AppEventBus.bindContainerAndHandler(this, object : SimpleEventHandler() {
            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserProfileEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                showData(event.profile)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserSetProfileEvent) {
                if (event.isFailed) {
                    return
                }
                showData(event.profile)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserSetPhotoEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                dismissProgressDialog()
                updatePhotos(event.photos)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: MediaSelectorResultEvent) {
                if (event.isMediaEmpty || event.type != IMAGE) {
                    return;
                }
                processMediaSelectorResult(event);
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserDeletePhotoEvent) {
                adapter.list.remove(event.item)
                adapter.notifyDataSetChanged()

                uploadPhotos()
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserVoiceEvent) {
                if (event.isNotFromThisRequestTag(requestTag)) {
                    return
                }
                updateVoice(event.voiceModel)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserUploadVoiceEvent) {
                updateVoice(event.voiceModel)
            }

            @Subscribe(threadMode = ThreadMode.MAIN)
            fun onEvent(event: UserVoiceUpdateEvent) {
                updateVoice(event.voiceModel)
            }
        })
    }

    private fun processMediaSelectorResult(event: MediaSelectorResultEvent) {
        showProgressDialog()
        when (event.fromType) {
            USER_INFO_EDIT -> {
                mAvatarDisposable = ImageFileCompressUtils.compressAsFileForAvatar(event.imagePathList[0])
                        .subscribeOn(Schedulers.io())
                        .observeOn(Schedulers.io())
                        .subscribe({ path ->
                            val avatar = UploadParam(path, UploadCategory.AVATAR, UploadMediaType.IMAGE, "", UploadImageOriginalType.COMPRESSED).uploadSync()
                            UserInfoData.setAvatar(requestTag, avatar)
                            dismissProgressDialog()
                        }, { t -> t.printStackTrace() })
            }
            USER_ALBUM -> {
                mPhotoDisposable = ImageFileCompressUtils.compressBatchAsFile(event.imagePathList)
                        .compose(RxUtils.ioToMainSingleScheduler())
                        .subscribe({ paths ->
                            UploadParam.batchUpload(paths.toList(), UploadCategory.ALBUM, UploadMediaType.IMAGE, "", UploadImageOriginalType.COMPRESSED, object : AppCallback<List<String>> {
                                override fun onSuccess(urls: List<String>) {
                                    val photos = ListUtil.convertToList(urls) { url -> UserAlbumItem(url) }
                                    adapter.list.addAll(photos)
                                    adapter.notifyDataSetChanged()
                                    uploadPhotos()
                                }

                                override fun onError(e: Throwable) {
                                    dismissProgressDialog()
                                    e.printStackTrace()
                                }
                            })
                        }, { t -> t.printStackTrace() })
            }
        }
    }

    private fun initData() {
        val user = (intent.getSerializableExtra(Constant.IntentKey.KEY_USER) as? User)
                ?: UserData.getInstance().user
        showUser(user)
        title = if (user.isSelf) AppContext.getString(R.string.user_info_edit_title) else user.remark
        initUIForOther(user.isSelf)
        UserInfoData.profile(requestTag, user.uid)
        getVoiceForSelf(user.isSelf)
    }

    private fun getVoiceForSelf(isSelf: Boolean) {
        if (!isSelf) {
            return
        }
        UserInfoData.getVoice(requestTag, UserData.getInstance().uid)
    }

    private fun initUIForOther(self: Boolean) {
        val visibility = if (self) View.VISIBLE else View.GONE
        album_title.visibility = visibility
        album_layout.visibility = visibility

        voice_title.visibility = visibility
        voice_layout.visibility = visibility

        avatar_layout.isEnabled = self
        avatar_arrow.visibility = visibility

        name_layout.isEnabled = self
        name_arrow.visibility = visibility

        birthday_layout.isEnabled = self
        birthday_arrow.visibility = visibility

//        profession_layout.isEnabled = self
//        profession_arrow.visibility = visibility

        height_layout.isEnabled = self
        height_arrow.visibility = visibility

        weight_layout.isEnabled = self
        weight_arrow.visibility = visibility

        size_layout.isEnabled = self
        size_arrow.visibility = visibility

        glamor_place_layout.isEnabled = self
        glamor_arrow.visibility = visibility

        annual_income_layout.isEnabled = self
        annual_arrow.visibility = visibility

        education_degree_layout.isEnabled = self
        education_arrow.visibility = visibility

        emotion_status_layout.isEnabled = self
        emotion_arrow.visibility = visibility

        inhabit_status_layout.isEnabled = self
        inhabit_arrow.visibility = visibility

        premarital_living_layout.isEnabled = self
        premarital_arrow.visibility = visibility

        accept_dates_layout.isEnabled = self
        accept_dates_arrow.visibility = visibility

        house_layout.isEnabled = self
        house_arrow.visibility = visibility

        car_layout.isEnabled = self
        car_arrow.visibility = visibility

        drink_layout.isEnabled = self
        drink_arrow.visibility = visibility

        cook_level_layout.isEnabled = self
        cook_arrow.visibility = visibility

        soliloquy_layout.isEnabled = self
        soliloquy_arrow.visibility = visibility
    }

    private fun showData(profile: UserProfile) {
        showUser(profile.user)
        birthday.text = profile.birthday
        constellation.text = profile.constellation
        location.text = getString(R.string.user_profile_edit_location, profile.province, profile.city, profile.county)
        profession.text = profile.profession
        height.text = profile.height
        weight.text = profile.weight
        size.text = profile.size
        glamor_place.text = profile.glamorPlace
        annual_income.text = profile.annualIncome
        education_degree.text = profile.educationDegree
        emotion_status.text = profile.emotionStatus
        inhabit_status.text = profile.inhabitStatus
        premarital_living.text = profile.premaritalLiving
        accept_dates.text = profile.acceptDates
        house.text = profile.house
        car.text = profile.car
        drink.text = profile.drink
        cook_level.text = profile.cookLevel
        soliloquy.text = profile.soliloquy
        updatePhotos(profile.photos)
        updateUI(profile)
    }

    private fun updateUI(profile: UserProfile) {
        val user = profile.user
        constellation_layout.visibility = getVisibility(user, profile.constellation)
        location_layout.visibility = getVisibility(user, profile.province + profile.city)
//        profession_layout.visibility = getVisibility(user, profile.profession)
        height_layout.visibility = getVisibility(user, profile.height)
        weight_layout.visibility = getVisibility(user, profile.weight)
        size_layout.visibility = getVisibility(user, profile.size)
        glamor_place_layout.visibility = getVisibility(user, profile.glamorPlace)
        annual_income_layout.visibility = getVisibility(user, profile.annualIncome)
        education_degree_layout.visibility = getVisibility(user, profile.educationDegree)
        emotion_status_layout.visibility = getVisibility(user, profile.emotionStatus)
        inhabit_status_layout.visibility = getVisibility(user, profile.inhabitStatus)
        premarital_living_layout.visibility = getVisibility(user, profile.premaritalLiving)
        accept_dates_layout.visibility = getVisibility(user, profile.acceptDates)
        house_layout.visibility = getVisibility(user, profile.house)
        car_layout.visibility = getVisibility(user, profile.car)
        drink_layout.visibility = getVisibility(user, profile.drink)
        cook_level_layout.visibility = getVisibility(user, profile.cookLevel)
        soliloquy_layout.visibility = getVisibility(user, profile.soliloquy)
    }

    private fun getVisibility(user: User, value: String): Int {
        return if (user.isSelf) {
            View.VISIBLE
        } else {
            if (value.isEmpty()) View.GONE else View.VISIBLE
        }
    }

    private fun updatePhotos(photos: List<UserAlbumItem>) {
        album_add.visibility = if (photos.size >= MAX_ALBUM_COUNT) View.GONE else View.VISIBLE
        album_title.text = getString(R.string.user_info_edit_photo_desc, photos.size.toString())
        adapter.list = photos
        adapter.notifyDataSetChanged()
        album_add.setViewTag(photos)
    }

    private fun showUser(user: User) {
        ImageViewUtil.loadImage(avatar, user, 48)
        name.setUser(user)
        sex.text = user.sexDesc
    }

    private fun showTimePicker() {
        val calendar = Calendar.getInstance();
        val curYear = calendar.get(Calendar.YEAR);
        val curMonth = calendar.get(Calendar.MONTH);
        val curDay = calendar.get(Calendar.DAY_OF_MONTH);

        val yearSelected = curYear - 23;
        val monthSelected = 0;
        val daySelected = 1;

        val yearMax = curYear - 18;
        val monthMax = 0;
        val dayMax = if (!isLeapYear(yearMax) && curMonth == Calendar.FEBRUARY && curDay == 29) curDay - 1 else curDay;

        val yearMin = curYear - 90;
        val monthMin = 0;
        val dayMin = 1;

        AlertHoloDateDialog.create(this)
                .setTitle(AppContext.getString(R.string.register_birthday_dialog_title))
                .setSelectedDate(yearSelected, monthSelected, daySelected)
                .setMaxDate(yearMax, monthMax, dayMax)
                .setMinDate(yearMin, monthMin, dayMin)
                .setOnDateResultListener { year, month, dayOfMonth ->
                    calendar.set(year, month, dayOfMonth)
                    val dateString = TimeUtils.getDate(calendar.time)
                    birthday.text = dateString
                    UserInfoData.setBirthday(requestTag, dateString)
                }
                .show()
    }

    private fun isLeapYear(yearMax: Int): Boolean {
        return (GregorianCalendar.getInstance() as GregorianCalendar).isLeapYear(yearMax)
    }

    private fun showProgressDialog() {
        progressDialog.setMessage(AppContext.getString(R.string.common_loading_please_wait))
        progressDialog.show()
    }

    private fun dismissProgressDialog() {
        progressDialog.dismiss()
    }

    override fun onItemMoved(fromPosition: Int, toPosition: Int) {
        uploadPhotos()
    }

    private fun uploadPhotos() {
        val photoUrls = ListUtil.convertToList(adapter.list) { item -> item.url }
        UserInfoData.setPhotos(requestTag, photoUrls)
    }

    private fun updateVoice(model: UserVoiceModel) {
        voice?.getViewTag<UserVoiceModel>()?.let {
            if (MP3PlayerUtils.getInstance().isSamePath(it.voiceUrl)) {
                destroyVoice()
            }
        }
        when (model.verifyStatus) {
            UserVoiceModel.VERIFYING -> {
                voice?.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_verifying, 0, 0, 0)
                voice?.setText(R.string.user_profile_voice_verifying)
                voice_retry_record.visibility = View.GONE
            }
            else -> {
                if (model.voiceUrl.isNotEmpty()) {
                    voice?.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_success, 0, 0, 0)
                    voice?.text = getString(R.string.user_profile_voice_success, model.duration.toString())
                    voice_retry_record.visibility = View.VISIBLE
                } else {
                    voice?.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_unverified, 0, 0, 0)
                    voice?.setText(R.string.user_profile_voice_unverified)
                    voice_retry_record.visibility = View.GONE
                }
            }
        }
        voice?.setViewTag(model)
    }

    private fun updatePlayLayout() {
        voice?.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_playing, 0, 0, 0)
        mVoicePlayerDisposable?.dispose()
        mVoicePlayerDisposable = Observable.interval(0, 1000L, TimeUnit.MILLISECONDS)
                .compose(RxUtils.ioToMainObservableScheduler())
                .subscribe({
                    val remainSec = (MP3PlayerUtils.getInstance().duration - MP3PlayerUtils.getInstance().currentPosition) / 1000
                    voice?.text = getString(R.string.user_profile_voice_success, remainSec.toString())
                }, { t -> t.printStackTrace() })
    }

    private fun pauseVoice() {
        mVoicePlayerDisposable?.dispose()
        voice?.getViewTag<UserVoiceModel>()?.let {
            val playing = MP3PlayerUtils.getInstance().isPlaying(it.voiceUrl)
            if (playing) {
                MP3PlayerUtils.getInstance().pause()
            }
        }
        voice?.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.icon_user_profile_voice_success, 0, 0, 0)
    }

    private fun destroyVoice() {
        mVoicePlayerDisposable?.dispose()
        voice?.getViewTag<UserVoiceModel>()?.let {
            val same = MP3PlayerUtils.getInstance().isSamePath(it.voiceUrl)
            if (same) {
                MP3PlayerUtils.getInstance().release()
            }
        }
    }

    private fun resumeVoice() {
        voice?.getViewTag<UserVoiceModel>()?.let {
            val isSamePath = MP3PlayerUtils.getInstance().isSamePath(it.voiceUrl)
            if (isSamePath) {
                MP3PlayerUtils.getInstance().resume()
                updatePlayLayout()
            }
        }
    }
}